home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Online / News / Thor / HD-Install / thor25_api.lha / ScriptServ / ScriptServ.c < prev    next >
C/C++ Source or Header  |  1995-08-20  |  16KB  |  661 lines

  1. /* ScriptServ.c
  2.     Auto: smake -f src:bbsread/ScriptServ/makefile
  3. */
  4.  
  5. #include <exec/types.h>
  6. #include <exec/memory.h>
  7. #include <exec/nodes.h>
  8. #include <exec/lists.h>
  9. #include <exec/semaphores.h>
  10. #include <libraries/dos.h>
  11. #include <dos/exall.h>
  12. #include <utility/tagitem.h>
  13. #include <proto/exec.h>
  14. #include <proto/dos.h>
  15. #include <proto/utility.h>
  16.  
  17. #include <stdio.h> 
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <ctype.h>
  21.  
  22. #include <libraries/bbsread.h>
  23. #include <proto/bbsread.h>
  24.  
  25. #define USESTRLEN                400L
  26. #define SIZE_EXALLBUFFER    256L
  27. #define CONFIG_VERSION        4L
  28.  
  29. /*  Global structure to hold librarybases  */
  30. struct TaskData
  31. {
  32.     struct ExecBase *SysBase;
  33.     struct DosLibrary *DOSBase;
  34.     struct Library *BBSReadBase;
  35.     struct Library *UtilityBase;
  36. };
  37.  
  38. #define SysBase        td->SysBase
  39. #define DOSBase        td->DOSBase
  40. #define BBSReadBase    td->BBSReadBase
  41. #define UtilityBase    td->UtilityBase
  42.  
  43. extern char *progname, *progdate;
  44. extern LONG *version, *revision;
  45.  
  46. /*  Prototypes for external functions  */
  47. extern APTR SPrintf(STRPTR dest, STRPTR fmtstr, ...);
  48. extern struct Library *OpenBRLibrary(struct ExecBase *, struct DosLibrary *, LONG);
  49.  
  50. /*  Prototypes for global functions  */
  51. struct Node * FindiName(struct List *list, STRPTR name);
  52. UBYTE *StripAnsi(UBYTE *s);
  53.  
  54. UBYTE *template = "BBSNAME,EVENT=EV/N/K/M,DONE/K,ERROR/K,WRITECFG/S,PACKAGEDONE/S,RENAMEGRAB/S,PRIVUPLOADFILE/K,UPDATEFILENOTES/K,USAGE/S";
  55.  
  56. enum {
  57.     TEM_BBSNAME,
  58.     TEM_EVENT,
  59.     TEM_DONE,
  60.     TEM_ERROR,
  61.     TEM_WRITECFG,
  62.     TEM_PACKAGEDONE,
  63.     TEM_RENAMEGRAB,
  64.     TEM_PRIVUPLOADFILE,
  65.     TEM_UPDATEFILENOTES,
  66.     TEM_USAGE,
  67.     TEM_NUMBEROF
  68. };
  69.  
  70. /*
  71.    Format of configuration file:
  72. VERSION        (4)
  73. BBSID
  74. BBSTYPE
  75. BBSDIR
  76. POSTCONF
  77. UPLOADDIR
  78. USERNAME
  79. USERSTREET
  80. USERADDRESS
  81. USERCOUNTRY
  82. USERPHONE
  83. NEWFILES            (y/n)
  84. AUTOPRIVDNL        (y/n)
  85. AUTOLOGOFF        (y/n)
  86. USECOLORS        (y/n)
  87. ANSIMENUES        (y/n)
  88. BULLETINS        (y/n)
  89. REPLYPACKET
  90. */
  91.  
  92. /*
  93.    Format of event file:
  94. EVENTNR        <- Use when marking done/error
  95. EVENT
  96. <tags in same order as in type config>
  97. */
  98.  
  99. STRPTR fmtstr =
  100. "%s V%ld.%ld\n"
  101. "Usage: %s [bbsname] [DONE eventnr] [ERROR eventnr] [WRITECFG]\n"
  102. "          [PACKAGEDONE] [RENAMEGRAB] [PrivUploadFile file]\n"
  103. "          [UpdateFileNotes file] [USAGE]\n"
  104. "Copyright © Ultima Thule Software %s  Author: Eivind Nordseth\n%s";
  105.  
  106. LONG __saveds NoName(void)
  107. {
  108.     struct TaskData TaskData, *td;
  109.     struct RDArgs *rdargs = NULL, *args = NULL;
  110.     STRPTR errmsg = NULL;
  111.     LONG array[TEM_NUMBEROF], retval = RETURN_FAIL, n;
  112.     struct TypeListItem *mytype = NULL;
  113.     struct BBSListItem *mybbs;
  114.     struct ConfListItem *myconf;
  115.     struct BBSData *bbsdata;
  116.     struct BBSInternal *bbsint;
  117.     struct UserData *userd = NULL;
  118.     struct List *bbslist = NULL, *conflist = NULL;
  119.     struct GlobalConfig *globalcfg = NULL;
  120.     struct ExAllControl *eac = NULL;
  121.     struct ExAllData *ead, *buffer = NULL;
  122.     STRPTR tobuf = NULL, confbuf = NULL, uplpath;
  123.     APTR eveobj = NULL;
  124.     ULONG eventnr, tobuflen = 0, confbuflen = 0;
  125.     TEXT filename[USESTRLEN];
  126.     BPTR fh = NULL, lock = NULL;
  127.     BYTE endchr;
  128.  
  129.     setmem(td = &TaskData, sizeof(struct TaskData), 0);
  130.     SysBase = *(struct ExecBase **)4;
  131.     
  132.     if(!(DOSBase = (struct DosLibrary *) OpenLibrary(DOSNAME, 0L))) return(10000L);
  133.     if(DOSBase->dl_lib.lib_Version < 37)
  134.     {
  135.         errmsg = "Needs Kick V37+";
  136.         goto quit;
  137.     }
  138.     if(!(UtilityBase = OpenLibrary("utility.library", 0L))) return(10000L);
  139.  
  140.     if(!(BBSReadBase = OpenBRLibrary(SysBase, DOSBase, 3L)))
  141.     {
  142.         errmsg = "Needs bbsread.library V3+";
  143.         goto quit;
  144.     }
  145.  
  146.      setmem(array, sizeof(ULONG) * TEM_NUMBEROF, '\0'); 
  147.  
  148.     if(!(args = AllocDosObject(DOS_RDARGS, NULL))) goto quit;
  149.  
  150.     SPrintf(args->RDA_ExtHelp = filename, fmtstr, progname, version, revision, 
  151.         progname, progdate, template);
  152.         
  153. /*    Printf("BufUsage: %ld\n", strlen(filename)); */
  154.  
  155.     if(!(rdargs = ReadArgs(template, array, args)))
  156.     {
  157.         errmsg = "Error in arguments.";
  158.         goto quit;
  159.     }
  160.  
  161.     if(array[TEM_USAGE] || !array[TEM_BBSNAME]) 
  162.     {
  163.         Printf(fmtstr, progname, version, revision, progname, progdate, "");
  164.         retval = RETURN_OK;
  165.         goto quit;
  166.     }
  167.     
  168.     if(!(globalcfg = GetGlobalConfig())) { errmsg = "Error geting global configuration."; goto quit; }
  169.  
  170.     if(!(bbslist = GetBBSList())) { errmsg = "Error geting bbslist."; goto quit; }
  171.  
  172.     if(!(mybbs = (struct BBSListItem *) FindiName(bbslist, (STRPTR) array[TEM_BBSNAME])))
  173.     {
  174.         errmsg = "Unknown BBS";
  175.         goto quit;
  176.     }
  177.  
  178.     if(!(mytype = TypeFromBBS(mybbs))) { errmsg =  "Error geting type."; goto quit; }
  179.  
  180.     if(!(conflist = GetConfList(mybbs))) { errmsg = "Error geting conflist."; goto quit; }
  181.  
  182.     bbsdata = mybbs->bl_Data;
  183.     bbsint  = mybbs->bl_Internal;
  184.  
  185.     if(array[TEM_DONE])
  186.     {
  187.         STRPTR ptr = (STRPTR) array[TEM_DONE];
  188.         ULONG flags;
  189.         APTR obj;
  190.  
  191.         eventnr = atol(ptr);
  192.         
  193.         while(isdigit(*ptr)) ptr++;
  194.  
  195.         if(!*ptr)
  196.         {
  197.             if(obj = ReadBREventTags(mybbs, eventnr, RBREV_Flags, &flags, TAG_END))
  198.             {
  199.                 if(!(flags & EDF_ERROR)) UpdateBREventTags(mybbs, eventnr, UBRE_SetDone, TRUE, TAG_END);
  200.                 FreeBRObject(obj);
  201.             }
  202.         }
  203.     }
  204.  
  205.     if(array[TEM_ERROR])
  206.     {
  207.         eventnr = atol((STRPTR) array[TEM_ERROR]);
  208.  
  209.         UpdateBREventTags(mybbs, eventnr, UBRE_SetError, TRUE, TAG_END);
  210.     }
  211.     
  212.     if(array[TEM_WRITECFG])
  213.     {
  214.         myconf = (struct ConfListItem *) &conflist->lh_Head;
  215.  
  216.         SPrintf(filename, "t:%s.CONFIG", bbsdata->bd_Name); 
  217.         if(!(fh = Open(filename, MODE_NEWFILE))) 
  218.         {
  219.             errmsg = "Unable to create config file";
  220.             goto quit;
  221.         }
  222.         FPrintf(fh, "%ld\n%s\n%s\n%s\n",
  223.             CONFIG_VERSION,
  224.             bbsdata->bd_GrabName,
  225.             mytype->tl_Data->td_TypeName,
  226.             mybbs->bl_BBSPath);
  227.         
  228.         while((myconf = (struct ConfListItem *) myconf->cl_Node.ln_Succ)->cl_Node.ln_Succ)
  229.         {
  230.             if(myconf->cl_Data->cd_Flags & CDF_MAIL) break;
  231.         }
  232.         if(!myconf->cl_Node.ln_Succ)
  233.         {
  234.             if(myconf = (struct ConfListItem *) conflist->lh_Head)
  235.             {
  236.                 if(myconf->cl_Node.ln_Succ) myconf = (struct ConfListItem *) myconf->cl_Node.ln_Succ;
  237.             }
  238.         }
  239.         if(myconf->cl_Node.ln_Succ) FPuts(fh, myconf->cl_Data->cd_Name); 
  240.         else FPuts(fh, "Post");
  241.         FPutC(fh,'\n');
  242.  
  243.         if(!(uplpath = bbsdata->bd_UploadPath)) 
  244.             if(!(uplpath = globalcfg->gc_UploadPath)) uplpath = "ram:";
  245.         
  246.         FPuts(fh, uplpath);
  247.         endchr = uplpath[strlen(uplpath) - 1];
  248.  
  249.         if(!(endchr == ':' || endchr == '/')) FPutC(fh, '/');
  250.  
  251.         if(!(userd = BBSUserData(globalcfg, mybbs)))
  252.         {
  253.             errmsg = "Unable to get BBS User Data";
  254.             goto quit;
  255.         }
  256.  
  257.         FPrintf(fh, "\n%s\n%s\n%s\n%s\n%s\n",
  258.             userd->ud_Name,
  259.             userd->ud_Street,
  260.             userd->ud_Address,
  261.             userd->ud_Country,
  262.             userd->ud_Phone);
  263.  
  264.         FPrintf(fh, "%lc\n%lc\n%lc\n%lc\n%lc\n%lc\n", 
  265.             bbsdata->bd_ScrFlags & SF_NEWFILES   ? 'y' : 'n',
  266.             bbsdata->bd_ScrFlags & SF_AUTOPDNL   ? 'y' : 'n',
  267.             bbsdata->bd_ScrFlags & SF_AUTOLOGOFF ? 'y' : 'n',
  268.             bbsdata->bd_ScrFlags & SF_USECOLORS  ? 'y' : 'n',
  269.             bbsdata->bd_ScrFlags & SF_ANSIMENUES ? 'y' : 'n',
  270.             bbsdata->bd_ScrFlags & SF_BULLETINS  ? 'y' : 'n');
  271.  
  272.         FPrintf(fh, "%s\n", bbsdata->bd_ReplyPacket ? bbsdata->bd_ReplyPacket : (STRPTR) "");
  273.  
  274.         Close(fh); fh = NULL;
  275.     }
  276.  
  277.     if(array[TEM_PACKAGEDONE])
  278.     {
  279.         for(n = bbsint->bi_FirstEvent; n <= bbsint->bi_LastEvent; n++)
  280.         {
  281.             ULONG flags;
  282.             APTR obj;
  283.  
  284.             if(obj = ReadBREventTags(mybbs, n, RBREV_Flags, &flags, TAG_END))
  285.             {
  286.                 if(flags & EDF_PACKED) UpdateBREventTags(mybbs, n, UBRE_SetDone, TRUE, TAG_END);
  287.                 FreeBRObject(obj);
  288.             }
  289.         }
  290.         PackDataFileTags(PD_EventData, mybbs, TAG_DONE);
  291.     }
  292.     
  293.     if(array[TEM_RENAMEGRAB])
  294.     {
  295.         STRPTR ptr;
  296.         BOOL more, match;
  297.  
  298.         if(!(lock = Lock(globalcfg->gc_DnloadPath, ACCESS_READ))) goto quit;
  299.         if(!(buffer  = AllocMem(SIZE_EXALLBUFFER, MEMF_ANY))) goto quit;
  300.         if(!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL))) goto quit;
  301.         
  302.         eac->eac_LastKey = (ULONG) (eac->eac_MatchString = (UBYTE *) (eac->eac_MatchFunc = NULL));
  303.         
  304.         do
  305.         {
  306.             more = ExAll(lock, buffer, SIZE_EXALLBUFFER, ED_TYPE, eac);
  307.             if((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) goto quit;
  308.  
  309.             if(eac->eac_Entries == 0) continue;
  310.  
  311.             for(ead = buffer; ead; ead = ead->ed_Next)
  312.             {
  313.                 if(ead->ed_Type > 0) continue;
  314.  
  315.                 match = !strnicmp(bbsdata->bd_GrabName, ead->ed_Name, strlen(bbsdata->bd_GrabName));
  316.                 ptr = &ead->ed_Name[strlen(bbsdata->bd_GrabName)];
  317.  
  318.                 if(match && (*ptr == '.' || *ptr == '\0'))
  319.                 {
  320.                     BPTR dlock, exist;
  321.                     LONG num = 0;
  322.                     
  323.                     dlock = CurrentDir(lock);
  324.                     do
  325.                     {
  326.                         num++;
  327.                         SPrintf(filename, "%s%ld%s", bbsdata->bd_GrabName, num, ptr);
  328.                         exist = Lock(filename, ACCESS_READ);
  329.                         if(exist) UnLock(exist);
  330.                     } while(exist);
  331.                     
  332.                     if(!Rename(ead->ed_Name, filename)) Printf("Unable to rename grab\n");
  333.                     CurrentDir(dlock);
  334.                     more = FALSE;
  335.                     break;
  336.                 }
  337.             }
  338.         } while(more);
  339.         UnLock(lock); lock = NULL;
  340.     }
  341.     
  342.     if(array[TEM_PRIVUPLOADFILE])
  343.     {
  344.         BOOL gotpriv = FALSE;
  345.  
  346.         if(!(fh = Open((STRPTR) array[TEM_PRIVUPLOADFILE], MODE_OLDFILE)))
  347.         {
  348.             errmsg = "Unable to open privuploadfile";
  349.             goto quit;
  350.         }
  351.  
  352.         while(FGets(fh, filename, USESTRLEN - 1))
  353.         {
  354.             STRPTR ptr = filename, end;
  355.  
  356.             if(!gotpriv)
  357.             {
  358.                 gotpriv = !strncmp(filename, "The following", 13);
  359.                 continue;
  360.             }
  361.  
  362.             if(!*ptr || *ptr == '\n') break;
  363.     
  364.             while(*ptr && *ptr == ' ') ptr++;
  365.             end = ptr;
  366.             while(*end && *end != ' ') end++;
  367.             *(end++) = '\0';
  368.  
  369.             while(*end && *end != '(') end++;
  370.             if(!(*end)) break;
  371.             
  372.             while(*end && *end != ',') end++;
  373.             if(!(*end)) break;
  374.             
  375.             while(*end && *end != ')') end++;
  376.             if(!(*end)) break;
  377.  
  378.             Printf("%s\n",ptr);
  379.         }
  380.         Close(fh); fh = NULL;
  381.     }
  382.     
  383.     if(array[TEM_UPDATEFILENOTES])
  384.     {
  385.         if(!(fh = Open((STRPTR) array[TEM_UPDATEFILENOTES], MODE_OLDFILE)))
  386.         {
  387.             errmsg = "Unable to open updatefilenotesfile";
  388.             goto quit;
  389.         }
  390.  
  391.         if(lock = Lock(bbsdata->bd_DnloadPath ? bbsdata->bd_DnloadPath : globalcfg->gc_DnloadPath, ACCESS_READ))
  392.         {
  393.             lock = CurrentDir(lock);
  394.  
  395.             while(FGets(fh, filename, USESTRLEN - 1))
  396.             {
  397.                 STRPTR ptr;
  398.  
  399.                 StripAnsi(filename);
  400.             
  401.                 if(strlen(filename) <= 40) continue;
  402.  
  403.                 for(ptr = &filename[2]; *ptr && *ptr != ' '; ptr++);
  404.                 *ptr = '\0';
  405.  
  406.                 if(*(ptr = &filename[39]) == ' ') ptr++;
  407.  
  408.                 if(filename[2]) SetComment(&filename[2], ptr);
  409.             }
  410.             
  411.             UnLock(CurrentDir(lock)); lock = NULL;
  412.         }
  413.     
  414.     }
  415.     if(array[TEM_EVENT])
  416.     {
  417.         ULONG **ptr = (ULONG **) array[TEM_EVENT];
  418.         ULONG eventmask = 0;
  419.     
  420.         while(*ptr)
  421.         {
  422.             ULONG eventnr = **(ptr++);
  423.  
  424.             if(eventnr < EVE_MAXEVENT) eventmask |= 1 << eventnr;
  425.         }
  426.  
  427.         SPrintf(filename, "t:%s.EVENTS", bbsdata->bd_Name); 
  428.         if(fh) Close(fh);
  429.         fh = NULL;
  430.  
  431.         for(n = bbsint->bi_FirstEvent; n <= bbsint->bi_LastEvent; n++)
  432.         {
  433.             struct EventConfigItem *eventcfg;
  434.             struct TagItem *tagitem, *eventtags;
  435.             STRPTR ptr, conf = NULL, nextconf = NULL, msgfile;
  436.             ULONG *tagptr, eventtype;
  437.             APTR obj;
  438.             LONGBITS flags;
  439.             BOOL multiple = FALSE;
  440.             TEXT filebuf[37];
  441.  
  442.             if(!(obj = ReadBREventTags(mybbs, n, 
  443.                 RBREV_EventTagsPtr, &eventtags,
  444.                 RBREV_EventType, &eventtype, 
  445.                 RBREV_Flags, &flags, TAG_END))) continue;
  446.  
  447.             if((flags & (EDF_DELETED | EDF_PACKED | EDF_ERROR | EDF_DONE | EDF_FREEZE)) || !((1<<eventtype) & eventmask))
  448.             {
  449.                 FreeBRObject(obj);
  450.                 continue;
  451.             }
  452.         
  453.             if(!fh)
  454.             {
  455.                 if(!(fh = Open(filename, MODE_NEWFILE))) 
  456.                 {
  457.                     errmsg = "Unable to create event file";
  458.                     goto quit;
  459.                 }
  460.             }
  461.  
  462.             eventcfg = (struct EventConfigItem *) &mytype->tl_Data->td_AvailEvents->mlh_Head;
  463.  
  464.             while((eventcfg = (struct EventConfigItem *) eventcfg->ec_Node.mln_Succ)->ec_Node.mln_Succ)
  465.             {
  466.                 if(eventcfg->ec_Event == eventtype) break;
  467.             }
  468.             if(!eventcfg->ec_Node.mln_Succ) { errmsg = "Event type panic"; goto quit; }
  469.  
  470.             if(ptr = (STRPTR) GetTagData(BREV_Conference, NULL, eventtags))
  471.             {
  472.                 if(strchr(ptr, ','))
  473.                 {
  474.                     ULONG len = strlen(ptr) + 1;
  475.  
  476.                     multiple = TRUE;
  477.                     if(len > confbuflen)
  478.                     {
  479.                         if(confbuf) FreeMem(confbuf, confbuflen);
  480.                         if(!(confbuf = AllocMem(confbuflen = len, MEMF_ANY))) goto quit;
  481.                     }
  482.                     strcpy(conf = confbuf, ptr);
  483.                 }
  484.                 else conf = ptr;
  485.             } 
  486.  
  487.             msgfile = (STRPTR) GetTagData(BREV_MsgFile, NULL, eventtags);
  488.  
  489.             if(msgfile && (GetTagData(BREV_PGPSignID, 0L, eventtags) || GetTagData(BREV_PGPEncryptID, 0L, eventtags)))
  490.             {
  491.                 strcpy(filebuf, msgfile);
  492.                 strcat(msgfile = filebuf, ".asc");
  493.             }
  494.             
  495.             do
  496.             {
  497.                 STRPTR to = NULL, nextto = NULL;
  498.  
  499.                 if(conf) if(nextconf = strchr(conf, ',')) *(nextconf++) = '\0';
  500.  
  501.                 if(ptr = (STRPTR) GetTagData(BREV_ToName, NULL, eventtags))
  502.                 {
  503.                     if(strchr(ptr, ','))
  504.                     {
  505.                         ULONG len = strlen(ptr) + 1;
  506.  
  507.                         multiple = TRUE;
  508.                         if(len > tobuflen)
  509.                         {
  510.                             if(tobuf) FreeMem(tobuf, tobuflen);
  511.                             if(!(tobuf = AllocMem(tobuflen = len, MEMF_ANY))) goto quit;
  512.                         }
  513.                         strcpy(to = tobuf, ptr);
  514.                     }
  515.                     else to = ptr;
  516.                 }
  517.  
  518.                 do
  519.                 {
  520.                     if(to) if(nextto = strchr(to, ',')) *(nextto++) = '\0';
  521.  
  522.                     FPrintf(fh, "%ld%s\n%ld\n", n, multiple ? "M" : "", eventtype);
  523.  
  524.                     if(tagptr = eventcfg->ec_NeedTags)
  525.                     {
  526.                         while(*tagptr)
  527.                         {
  528.                             if(!((*tagptr == BREV_PGPSignID) || (*tagptr == BREV_PGPEncryptID)))
  529.                             {
  530.                                 if(tagitem = FindTagItem(*tagptr, eventtags))
  531.                                 {
  532.                                     if(*tagptr == BREV_Conference) FPuts(fh, conf);
  533.                                     else if(*tagptr == BREV_ToName) FPuts(fh, to);
  534.                                     else if(*tagptr == BREV_MsgFile) FPuts(fh, msgfile);
  535.                                     else if(*tagptr == BREV_Date)
  536.                                     {
  537.                                         struct ClockData cd[1];
  538.                                 
  539.                                         Amiga2Date(tagitem->ti_Data, cd);
  540.                                     
  541.                                         FPrintf(fh, "%02ld%02ld%02ld", cd->year % 100, cd->month, cd->mday);
  542.                                     }
  543.                                     else if(*tagptr & BR_TagString) FPuts(fh, (STRPTR) tagitem->ti_Data);
  544.                                     else FPrintf(fh, "%ld", tagitem->ti_Data);
  545.                                 }
  546.                                 FPutC(fh, '\n');
  547.                             }
  548.                             tagptr++;
  549.                         }
  550.                     }
  551.  
  552.                     if(tagptr = eventcfg->ec_OptTags)
  553.                     {
  554.                         while(*tagptr)
  555.                         {
  556.                             if(!((*tagptr == BREV_PGPSignID) || (*tagptr == BREV_PGPEncryptID)))
  557.                             {
  558.                                 if(tagitem = FindTagItem(*tagptr, eventtags))
  559.                                 {
  560.                                     if(*tagptr == BREV_Conference) FPuts(fh, conf);
  561.                                     else if(*tagptr == BREV_ToName) FPuts(fh, to);
  562.                                     else if(*tagptr == BREV_MsgFile) FPuts(fh, msgfile);
  563.                                     else if(*tagptr == BREV_Date)
  564.                                     {
  565.                                         struct ClockData cd[1];
  566.                                 
  567.                                         Amiga2Date(tagitem->ti_Data, cd);
  568.                                     
  569.                                         FPrintf(fh, "%02ld%02ld%02ld", cd->year % 100, cd->month, cd->mday);
  570.                                     }
  571.                                     else if(*tagptr & BR_TagString) FPuts(fh, (STRPTR) tagitem->ti_Data);
  572.                                     else FPrintf(fh, "%ld", tagitem->ti_Data);
  573.                                 }
  574.                                 FPutC(fh, '\n');
  575.                             }
  576.                             tagptr++;
  577.                         }
  578.                     }
  579.                 } while(to = nextto);
  580.             } while(conf = nextconf);
  581.  
  582.             if(multiple) FPrintf(fh, "%ld\n%ld\n", n, 7769);
  583.  
  584.             FreeBRObject(obj);
  585.         }
  586.  
  587.         if(!fh) DeleteFile(filename);
  588.     }
  589.  
  590. done:   /*  All stuff is done  */
  591.  
  592.     retval = RETURN_OK;
  593.  
  594.     Flush(Output());
  595.  
  596. quit:
  597.     if(errmsg)
  598.     {
  599.         Write(Output(), errmsg, strlen(errmsg));
  600.         Write(Output(), "\n", 1);
  601.     }
  602.     if(eveobj) FreeBRObject(eveobj);
  603.     if(userd) FreeBRObject(userd);
  604.     if(mytype) FreeBRObject(mytype);
  605.     if(conflist) FreeBRObject(conflist);
  606.     if(bbslist) FreeBRObject(bbslist);
  607.     if(globalcfg) FreeBRObject(globalcfg);
  608.  
  609.     if(rdargs) FreeArgs(rdargs);
  610.     if(args)   FreeDosObject(DOS_RDARGS, args);
  611.  
  612.     if(confbuf) FreeMem(confbuf, confbuflen);
  613.     if(tobuf)   FreeMem(tobuf, tobuflen);
  614.  
  615.     if(fh) Close(fh);
  616.     if(lock) UnLock(lock);
  617.     if(eac) FreeDosObject(DOS_EXALLCONTROL, eac);
  618.     if(buffer) FreeMem(buffer, SIZE_EXALLBUFFER);
  619.     if(BBSReadBase) CloseLibrary(BBSReadBase);
  620.     if(UtilityBase) CloseLibrary(UtilityBase);
  621.     CloseLibrary((struct Library *) DOSBase);
  622.     return(retval);
  623. }
  624.  
  625.  
  626. struct Node * FindiName(
  627. struct List *list, 
  628. STRPTR name)
  629. {
  630.     struct Node *node = (struct Node *) &list->lh_Head;
  631.     
  632.     while((node = node->ln_Succ)->ln_Succ)
  633.     {
  634.         if(!stricmp(name, node->ln_Name)) return(node);
  635.     }
  636.     return(NULL);
  637. }
  638.  
  639. UBYTE *StripAnsi(UBYTE *s)
  640. {
  641.     STRPTR dest = s, d = s;
  642.     
  643.     while(*s)    
  644.     {
  645.         if((*s == 0x1b) || (*s == 0x9b))
  646.         {
  647.             if(*s == 0x1b)
  648.             {
  649.                 if(*++s != '[') continue;
  650.             }
  651.             s++;
  652.             while(*s && *s < '@') s++;
  653.         }
  654.         else if(*s >= 32) *d++ = *s;
  655.         s++;
  656.     }
  657.     *d = '\0';
  658.  
  659.     return(dest);
  660. }
  661.